//
// Created on 2024/1/4.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef MyApplication_Libuv_H
#define MyApplication_Libuv_H
#include <napi/native_api.h>
#include <napi/native_api.h>
#include <unordered_map>
#include <uv.h>
#include <vector>

typedef struct {
    void *data;
} IdleMessage; // ts线程发送的消息的数据结构

class TSMessage {
public:
    void *data;
}; // ts线程发送的消息的数据结构

class Libuv {
private:
    static Libuv *instance;

public:
    static void init(napi_env env) {
        if (Libuv::instance == nullptr) {
            Libuv::instance = new Libuv(env);
        }
    }
    static Libuv *GetInstance() { return instance; }
    void addIdleHandler(IdleMessage *message) {
        if (uv_is_active(reinterpret_cast<uv_handle_t *>(&m_MainOnMessage))) {
            m_idle.data = message;
            uv_idle_start(&m_idle, idle_callback);
        }
    }

    void sendMessage(TSMessage *message) {
        if (!message) {
            return;
        }
        if (uv_is_active(reinterpret_cast<uv_handle_t *>(&m_MainOnMessage))) {
            uv_rwlock_wrlock(&m_MessagesLock);
            m_TSPendingMessages.push_back(message);
            uv_rwlock_wrunlock(&m_MessagesLock);
            m_MainOnMessage.data = this;
            uv_async_send(&m_MainOnMessage);
        } else {
            // do nothing
        }
    }

private:
    static void onHandleMessage(uv_async_t *data) {
        Libuv *instance = reinterpret_cast<Libuv *>(data->data);
        if (instance) {
            // todo
        }
    }
    static void idle_callback(uv_idle_t *handle) {
        auto instance = Libuv::GetInstance();
        if (!instance) {
            return;
        }
        IdleMessage *message = reinterpret_cast<IdleMessage *>(handle->data);
        // todo
        uv_idle_stop(handle);
    }
    Libuv(napi_env env) : m_env(env) {
        uv_rwlock_init(&m_MessagesLock);
        if (napi_get_uv_event_loop(env, &(this->m_MainThreadLoop)) == napi_ok) {
            if (this->m_MainThreadLoop) {
                uv_async_init(this->m_MainThreadLoop, &m_MainOnMessage, onHandleMessage);
                uv_idle_init(this->m_MainThreadLoop, &this->m_idle);
            }
        }
    }
    ~Libuv();

private:
    napi_env m_env = nullptr;
    uv_loop_t *m_MainThreadLoop = nullptr;
    uv_async_t m_MainOnMessage;
    uv_idle_t m_idle;
    std::vector<TSMessage *> m_TSPendingMessages;

    std::unordered_map<long, bool> m_idleMessageMap;
    uv_rwlock_t m_MessagesLock;
};
#endif // MyApplication_Libuv_H
